﻿#include "WRType.h"
#include <QHash>
#include <QMutex>
#include <QMutexLocker>

#include "WRException.h"

//表示类型。
class WRTypeManager
{
private:
    //同步锁。
    QMutex m_mutex;
    //类型表。
    QHash<QUuid, WRType*> m_table;

public:
    //初始化。
    inline WRTypeManager(void)
    {
        //add code here
    }
    //释放资源。
    inline ~WRTypeManager(void)
    {
        for(QHash<QUuid, WRType*>::Iterator iter = m_table.begin(); iter != m_table.end(); ++iter)
        {
            WRType* entry = iter.value();
            delete entry;
        }
    }

    //获取指定类型。
    inline WRType* select(const QUuid& uuid)
    {
        QMutexLocker lock(&m_mutex);
        QHash<QUuid, WRType*>::ConstIterator iter = m_table.find(uuid);
        if (iter != m_table.end())
        {
            return iter.value();
        }
        return 0;
    }
    //注册新的类型。
    inline WRType* enroll(const QUuid& uuid, WRType* base)
    {
        QMutexLocker lock(&m_mutex);        
        QHash<QUuid, WRType*>::const_iterator iter = m_table.find(uuid);
        if (iter != m_table.end())
        {
            WRType* entry = iter.value();
            if (entry->base() != base)
            {
                throw WRException();
            }
            return entry;
        }
        else
        {
            WRType *entry = new WRType(uuid, base);
            m_table.insert(uuid, entry);
            return entry;
        }
    }

    //创建新的类型。
    inline WRType* create(const void* buf, WR32s cnt)
    {
        if (cnt > 0)
        {
            const unsigned char* data = (const unsigned char*)buf;

            QMutexLocker lock(&m_mutex);

            WRType* base = 0;
            for(WR32s i = 0; i < cnt; ++i)
            {
                QUuid uuid = WRBytes::read<QUuid>(data + i * sizeof(QUuid));
                QHash<QUuid, WRType*>::ConstIterator iter = m_table.find(uuid);
                if (iter != m_table.end())
                {
                    base = iter.value();
                    WRType* base2 = base->base();
                    for(WR32s j = i + 1; j < cnt; ++j)
                    {
                        uuid = WRBytes::read<QUuid>(data + j * sizeof(QUuid));
                        if (!base2 || base2->uuid() != uuid)
                        {
#ifdef WRDEBUG
                            throw WRException();
#endif
                            return 0;
                        }
                        base2 = base2->base();
                    }
                    cnt = i;
                    break;
                }
            }
            for(WR32s i = cnt - 1; i >= 0; --i)
            {
                QUuid uuid = WRBytes::read<QUuid>(data + i * sizeof(QUuid));
                base = new WRType(uuid, base);
                m_table.insert(uuid, base);
            }
            return base;
        }
        return 0;
    }
};

namespace WR
{
    //获取类型管理者实例。
    WRTypeManager* typeManager(void)
    {
        static WRTypeManager value;
        return &value;
    }
}

//获取指定类型。
WRType* WRType::select(const QUuid& uuid)
{
    WRTypeManager* manager = WR::typeManager();
    return manager->select(uuid);
}
//注册新的类型。
WRType* WRType::enroll(const QUuid& uuid, WRType* base)
{
    WRTypeManager* manager = WR::typeManager();
    return manager->enroll(uuid, base);
}

//将类型写入数据中。
WR32s WRType::toBytes(void* buf) const
{
    if (buf != 0)
    {
        unsigned char* b = (unsigned char*)buf;
        WRBytes::write(m_uuid, b);
        b += sizeof(QUuid);
        WR32s c = 1;
        WRType* p = base();
        while(p != 0)
        {
            WRBytes::write(p->m_uuid, b);
            b += sizeof(QUuid);
            ++c;
            p = p->base();
        }
        return c;
    }
    else
    {
        WR32s c = 1;
        WRType* p = base();
        while(p != 0)
        {
            ++c;
            p = p->base();
        }
        return c;
    }
}
//创建新的类型。
WRType* WRType::fromBytes(const void* buf, WR32s cnt)
{
    WRTypeManager* manager = WR::typeManager();
    return manager->create(buf, cnt);
}
